package myJs.myPkg.reactHookForm

import japgolly.scalajs.react.ReactEventFromInput
import myJs.Implicits.FieldValue
import myJs.myPkg.ReactRef
import myJs.myPkg.rSelect.SelectOption
import myJs.myPkg.reactHookForm.ReactHookForm.ValidateR
import org.scalajs.dom.html
import slinky.readwrite.ObjectOrWritten

import scala.concurrent.Future
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport
import scala.scalajs.js.|

/**
	*Created by yz on 20/9/2023
	*/
@js.native
trait Control extends js.Object {}

@js.native
trait ErrorField extends js.Object {

  val message: js.UndefOr[String] = js.native

  val `type`: js.UndefOr[String] = js.native

}

@js.native
trait FormStateRT extends js.Object {

  def errors: js.Dictionary[ErrorField] = js.native

}

case class SetValueOptions(
  shouldValidate: js.UndefOr[Boolean] = js.undefined
)

case class UseFormOptions(
  mode: String = "onSubmit",
  reValidateMode: String = "onChange",
  resolver: js.UndefOr[Resolver] = js.undefined
)

@js.native
trait RegisterRT extends js.Object {

//  type ChangeHandler = SyntheticEvent[TagElement#RefType, Event] => Unit

  def name: String = js.native

//  def onChange: js.Function1[SyntheticEvent[TagElement#RefType, Event], Unit] = js.native

//  def ref: ReactRef[html.Input] = js.native

//  def onBlur: ChangeHandler = js.native

}

@js.native
trait UseFormRT extends js.Object {

  type SubmitHandler = js.Function1[js.Dictionary[js.Any], js.Any]

  def register(name: String): RegisterRT = js.native

  def register(name: String, options: ObjectOrWritten[RegisterOptions]): RegisterRT = js.native

  def formState: FormStateRT = js.native

  def handleSubmit(onValid: SubmitHandler): js.Function1[ReactEventFromInput,Unit] = js.native

  def watch(name: String): FieldValue = js.native

  def getFieldState(name: String): FieldStateT = js.native

  def setValue(
    name: String,
    value: js.UndefOr[String | js.Array[String] | Boolean | SelectOption],
    options: js.UndefOr[ObjectOrWritten[SetValueOptions]] = js.undefined
  ): Unit = js.native
//  def setError(name: String, error: ObjectOrWritten[FieldError]): Unit = js.native
  def clearErrors(name: String): Unit = js.native

  def trigger(name: String): Unit = js.native

  def control: Control = js.native

  def reset[T](options: ObjectOrWritten[T]): Unit = js.native



}

case class UseFormStateOptions(
  name: js.UndefOr[String | List[String]] = js.undefined
)

case class ValidationValueMessage(
  value: js.UndefOr[Boolean | js.RegExp | Int] = js.undefined,
  message: js.UndefOr[String] = js.undefined
)

case class RegisterOptions(
  required: js.UndefOr[ValidationValueMessage] = js.undefined,
  valueAsNumber: js.UndefOr[Boolean] = js.undefined,
  pattern: js.UndefOr[ValidationValueMessage] = js.undefined,
  min: js.UndefOr[ValidationValueMessage] = js.undefined,
  max: js.UndefOr[ValidationValueMessage] = js.undefined,
  validate: js.UndefOr[String => ValidateR | Future[ValidateR]] = js.undefined,
  minLength: js.UndefOr[ValidationValueMessage] = js.undefined
)

case class UseControllerOptions(
  name: String,
  rules: js.UndefOr[RegisterOptions] = js.undefined,
  defaultValue: js.UndefOr[String | List[String]] = js.undefined
)

@js.native
trait FieldT extends js.Object {
  def name: String = js.native

  def value: FieldValue = js.native

  def onChange: js.Function1[js.Array[String] | String, Unit] = js.native

  def ref: ReactRef[html.Select] = js.native

  def onBlur: js.Function1[ReactEventFromInput,Unit] = js.native

}

@js.native
trait ItemT extends js.Object {

  val id: String = js.native

}

@js.native
trait UseFieldArrayRT extends js.Object {

  def fields: js.Array[ItemT] = js.native

  def append[T](data: ObjectOrWritten[T]): Unit = js.native

  def insert[T](curI: Int, data: ObjectOrWritten[T]): Unit = js.native

  def remove(curI: Int): Unit = js.native
  def remove(curI: ObjectOrWritten[List[Int]]): Unit = js.native

  def remove(): Unit = js.native

}

@js.native
trait FieldStateT extends js.Object {
  val error: js.UndefOr[ErrorField] = js.native
}

@js.native
trait UseControllerRT extends js.Object {
  val field: FieldT = js.native
  val fieldState: FieldStateT = js.native
}

case class UseFieldArrayOptions(
  control: js.UndefOr[Control]=js.undefined,
  name: String,
  shouldUnregister: js.UndefOr[Boolean] = js.undefined
)

@JSImport("react-hook-form", JSImport.Default)
@js.native
object ReactHookForm extends js.Object {

  type ValidateR = Boolean | String

  def useForm(options: ObjectOrWritten[UseFormOptions]): UseFormRT = js.native

  def useFormState(options: ObjectOrWritten[UseFormStateOptions]): FormStateRT = js.native

  def useController(options: ObjectOrWritten[UseControllerOptions]): UseControllerRT = js.native

  def useFormContext(): UseFormRT = js.native

  def useFieldArray(
    options: ObjectOrWritten[UseFieldArrayOptions]
  ): UseFieldArrayRT = js.native

}
